#include <iostream>
#include <sys/socket.h>
#include <signal.h>
#include <list>
#include <sys/types.h>
#include <pwd.h>
#include "../socks/sock.h"
#include "../socks/sockdist.h"

using namespace std;

string recv_str(int desc);


struct myClient {
	int desc;
	string name;
	struct sockaddr_in BR;
	socklen_t lg;
};

list<struct myClient *> listDesc;
struct sigaction sig_quit;
void quit(int signal);

int main(int argc, char** argv)
{
	sig_quit.sa_handler = quit;
	sigaction(SIGINT, &sig_quit, NULL);

	if(argc > 1)
	{
		Sock BRserver(SOCK_STREAM, (short) atoi(argv[1]), 0);
		int descBRserver;
		
		if(BRserver.good())
		{
			descBRserver = BRserver.getsDesc();
		}
	
		fd_set set;
		
		int maxDesc = descBRserver + 1;
		//struct myClient serv;
		//serv.desc = descBRserver;
		//serv.name = "Serveur";
		//listDesc.push_back(serv);
		
		cout << "Ready !" << endl;
		
		while(true)
		{
			cout << "Waiting ...";
			FD_ZERO(&set);
			
			for(list<struct myClient *>::iterator it = listDesc.begin(); it != listDesc.end(); ++it)
			{
				FD_SET((*it)->desc, &set);
			}
			
			FD_SET(descBRserver, &set);
			
			int nbReady = select(maxDesc + 1, &set, NULL, NULL, NULL);
				
			if(nbReady > 0)
			{
				
				cout << "OK" << endl;
				for(list<struct myClient *>::iterator it = listDesc.begin(); it != listDesc.end(); ++it)
				{
					if( FD_ISSET((*it)->desc, &set) )
					{
						/// New msg
						
						string texte = recv_str((*it)->desc);
						
						if(texte == "\\quit")
						{
							texte = "-- Deconnection : "+(*it)->name;
							listDesc.erase(it);
							--it;
							cout << "deco" << endl;
						}
						else
						{
							texte = (*it)->name+" : "+texte;
						}
							
						for(list<struct myClient *>::iterator c = listDesc.begin(); c != listDesc.end(); ++c)
						{
							int size = texte.length();
							
							int res_send = send((*c)->desc, &size, sizeof(texte.length()), 0);
							res_send = send((*c)->desc, texte.c_str(), texte.length(), 0);
						}
					}
				}
				
				if(FD_ISSET(descBRserver, &set) )
				{
					
					cout << "1" << endl;
					struct myClient * cv = new struct myClient;
					
					int res = listen(descBRserver, 5);
					if(res == -1)
					{
						cout << "Erreur listen" << endl;
					}
					cv->lg = sizeof(struct sockaddr_in);
					int descBRcv = accept(descBRserver, (struct sockaddr*)&cv->BR, &cv->lg);
					
					cout << "b" << endl;
					string nom = recv_str(descBRcv);
					
					cout << "nom" << endl;
					
					cv->desc = descBRcv;
					cv->name = nom;
					maxDesc = max(descBRcv + 1, maxDesc);
					
					cout << "New" << endl;
					
					int t = listDesc.size();
					cout << t << endl;
					int res_send = send(descBRcv, &t, sizeof(t), 0);
					
					string texte;
					
					for(list<struct myClient *>::iterator c = listDesc.begin(); c != listDesc.end(); ++c)
					{
						
						texte = "** Nouveau client : "+cv->name;
						int size = texte.length();
						
						int res_send = send((*c)->desc, &size, sizeof(size), 0);
						res_send = send((*c)->desc, texte.c_str(), texte.length(), 0);
						
						texte = "** Nouveau client : "+(*c)->name;
						size = texte.length();
						res_send = send(cv->desc, &size, sizeof(size), 0);
						res_send = send(cv->desc, texte.c_str(), texte.length(), 0);
					}
					
					listDesc.push_back(cv);
					
				}
			}
			else
			{
				/// Error
			}
		}
	}

	cout << endl;
}


string recv_str(int desc)
{
	int size = 0;
	int res_recv;
	
	res_recv = recv(desc, &size, sizeof(size), 0);
	if(res_recv == -1)
	{
		cout << "Erreur";
		return "";
	}
	
	char *msg = new char[size+1];
	
	for(int k(0); k<size; k++)
	{
		res_recv = recv(desc, &msg[k], sizeof(msg[k]), 0);
		if(res_recv == -1)
		{
			cout << "!" << endl;
			msg[k] = '?';
		}
	}
	
	msg[size] = '\0';
	
	return (string)msg;
}

void quit(int signal)
{
	string c_send = "\\quit";
	int size = c_send.length();
	
	for(list<struct myClient *>::iterator c = listDesc.begin(); c != listDesc.end(); ++c)
	{
		int res_send = send((*c)->desc, &size, sizeof(c_send.length()), 0);
		res_send = send((*c)->desc, c_send.c_str(), c_send.length(), 0);
	}

	cout << endl;

	exit(0);
}
